home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-04-25 | 9.3 KB | 304 lines | [TEXT/CWIE] |
- // ==================================================
- // UStandardFiles.cp
- // Copyright (C) 1994-1997 Mizutori Tetsuya
- // March 5, 1997
- // ==================================================
- // All documents are pretty-printed in 10-point Geneva font.
-
- #include <Files.h>
- #include <Processes.h>
- #include <Types.h>
- #include <LowMem.h>
-
- #include "UStandardFiles.h"
- #include <UEnvironment.h>
-
-
- // ==================================================
- // Select file or directory
- // ==================================================
- // This code for StandardGetFileOrDirectory() is greatly due to
- // Metrowerks CodeWarrior PowerPlant.
-
- // Local Constants
-
- const ResIDT DLOG_SelectFile = 600;
- const short item_SelectThisButton = 10;
- const unsigned char mask_IsFolder = 0x10;
- const char replaceBy_thisName = '^';
-
-
- // static Class variables
- Str63 UStandardFiles::sCurrentName;
- Str255 UStandardFiles::sSavedString;
- Boolean UStandardFiles::sCustomSelection;
-
-
- // ==================================================
- // • Constructors
- // ==================================================
-
- // --------------------------------------------------
- // • UStandardFiles()
- // --------------------------------------------------
-
- UStandardFiles::UStandardFiles()
- {
- }
-
-
- // --------------------------------------------------
- // • ~UStandardFiles()
- // --------------------------------------------------
-
- UStandardFiles::~UStandardFiles()
- {
- }
-
-
- // --------------------------------------------------
- // • StandardGetFileOrDirectory
- // --------------------------------------------------
- // Prompts the user to select a plain file or directory using a modified
- // version of the Standard Get File dialog box.
- // An extra "Select Item" button is added.
- //
- // Returns true if the user selected a plain file or directory, in which case the
- // StandardFileReply will contain info about the selected item.
- // ioReply->sfGood {true if selected a plain file or directory}
- // ioReply->sfFile {file spec for the selected file, folder, or volume}
- // ioReply->sfType {its file type for a plain file; 'fold' for folder or 'disk' for volume}
- // ioReply->sfIsFolder {true if the selected item is a folder or volume}
- // ioReply->sfIsVolume {true if the selected item is a volume}
-
- // Returns false if the user cancelled the action.
- // ioReply->sfGood {false if the user cancelled the action}
-
- Boolean
- UStandardFiles::StandardGetFileOrDirectory(
- FileFilterUPP inFileFilter, // This file filter function is ignored.
- short inNumTypes,
- ConstSFTypeListPtr inTypeList,
- StandardFileReply * ioReply )
- {
- #pragma unused ( inFileFilter )
-
- sCustomSelection = false;
- // SFTypeList theTypeList;
- Point where = {-1, -1};
-
- // Allocate Routine Descriptors
- FileFilterYDUPP fileFilter = NewFileFilterYDProc( FileFilter_SelectFile );
- DlgHookYDUPP dlgHook = NewDlgHookYDProc( DialogHook_SelectFile );
-
- // Display "SelectFile" Dialog
- // ::CustomGetFile( fileFilter, -1, theTypeList, ioReply, DLOG_SelectFile,
- ::CustomGetFile( fileFilter, inNumTypes, inTypeList, ioReply, DLOG_SelectFile,
- where, dlgHook, NULL, NULL, NULL, ioReply );
-
- // Free Routine Descriptors
- DisposeRoutineDescriptor( fileFilter );
- DisposeRoutineDescriptor( dlgHook );
-
- ioReply->sfGood = ( ioReply->sfGood || sCustomSelection );
-
- return ( ioReply->sfGood );
- }
-
-
- // --------------------------------------------------
- // • FileFilter_SelectFile
- // --------------------------------------------------
- // Standard File filter function
-
- pascal Boolean
- UStandardFiles::FileFilter_SelectFile(
- CInfoPBPtr inPB,
- void * inDataPtr )
- {
- #pragma unused ( inPB, inDataPtr )
-
- // OSType theType = (inPB->hFileInfo).ioFlFndrInfo.fdType;
-
- // Screens out everything except directories (folders and volumes)
- // If the file is not a folder, then returns true.
- // return ( (inPB->dirInfo.ioFlAttrib & mask_IsFolder) == 0 );
-
- // This filter passes through any ones.
- return false;
- }
-
-
- // --------------------------------------------------
- // • DialogHook_SelectFile
- // --------------------------------------------------
- // Standard File dialog hook
- // Handles a "Select File" button in the custom standard get file dialog box.
- //
- // The item number of the "Select File" button is item_SelectThisButton.
-
- pascal short
- UStandardFiles::DialogHook_SelectFile(
- short inItem,
- DialogPtr inDialog,
- void * ioDataPtr ) // Ptr to StandardFileReply
- {
- // This Hook is only for the main dialog box (not a sub dialog)
- if (::GetWRefCon(inDialog) != sfMainDialogRefCon ) {
- return inItem;
- }
-
- short itemHit = inItem;
- Str255 itemName;
-
- // Directory Info Parameter Block
- CInfoPBRec thePB;
- thePB.dirInfo.ioCompletion = NULL;
- thePB.dirInfo.ioNamePtr = itemName;
- thePB.dirInfo.ioFDirIndex = -1;
-
- // Get Handle to "Select File" button
- short buttonType;
- Handle buttonH;
- Rect buttonRect;
- ::GetDialogItem( inDialog, item_SelectThisButton, &buttonType, &buttonH, &buttonRect );
-
- if ( inItem == sfHookFirstCall ) {
-
- // First call, save original button name
- ::GetControlTitle( (ControlHandle) buttonH, sSavedString );
-
- // On first call, nothing is selected. Get name of current directory
- thePB.dirInfo.ioVRefNum = -LMGetSFSaveDisk();
- thePB.dirInfo.ioDrDirID = LMGetCurDirStore();
- ::PBGetCatInfoSync( &thePB );
- SetSelectButtonTitle( (ControlHandle) buttonH, buttonRect, itemName );
-
- } else {
-
- StandardFileReply * replyP = (StandardFileReply *) ioDataPtr;
-
- if ( replyP->sfIsFolder || replyP->sfIsVolume ) {
-
- // Selected file type is a folder 'fold'.
- replyP->sfType = 'fold';
- if ( replyP->sfIsVolume ) replyP->sfType = 'disk';
- // Folder or Volume is selected. Copy its name
- ::BlockMoveData( replyP->sfFile.name, itemName, StrLength(replyP->sfFile.name) + 1 );
-
- } else if ( replyP->sfFile.name[0] != 0 ) {
-
- // Selected file type is its file type. (do nothing, here)
- // replyP->sfType = replyP->sfType;
- // A plain file is selected. Copy its name
- ::BlockMoveData( replyP->sfFile.name, itemName, StrLength(replyP->sfFile.name) + 1 );
-
- } else {
-
- // No file or directory selected. Find the Directory being viewed
- thePB.dirInfo.ioVRefNum = replyP->sfFile.vRefNum;
- thePB.dirInfo.ioDrDirID = replyP->sfFile.parID;
- ::PBGetCatInfoSync( &thePB );
-
- // Since this Directory is not selected
- // some fields of the SF Reply will
- // not be filled in. We must fill in:
- // Is the Directory a Folder?
- // Is the Directory a Volume?
- // Script Code
- // FSSpec for Directory
-
- // Selected file type is 'fold' for a folder or volume.
- replyP->sfType = 'fold';
- // Directory is always a Folder
- replyP->sfIsFolder = true;
- // Volumes have special DirID
- replyP->sfIsVolume = (thePB.dirInfo.ioDrDirID == fsRtDirID);
- if ( replyP->sfIsVolume ) replyP->sfType = 'disk';
- // Directory name uses System Script
- replyP->sfScript = smSystemScript;
- // Fill in FSSpec for the Directory
- ::FSMakeFSSpec( thePB.dirInfo.ioVRefNum, thePB.dirInfo.ioDrParID,
- itemName, &replyP->sfFile );
-
- }
-
- // Change name of Select button to name of this selected item.
- if ( IUEqualString(itemName, sCurrentName) == 1 ) {
- SetSelectButtonTitle( (ControlHandle) buttonH, buttonRect, itemName );
- }
-
- if ( inItem == item_SelectThisButton ) {
- // User clicked our "Select Directory" button.
- // Must fake a "Cancel" button click to dismiss dialog box.
- itemHit = sfItemCancelButton;
- // Set global flag so we know the user selected a directory
- // (to distinguish this from a "real" cancel)
- sCustomSelection = true;
- }
- }
-
- return itemHit;
- }
-
-
- // --------------------------------------------------
- // • SetSelectButtonTitle
- // --------------------------------------------------
- // Sets the Title of the Button for selecting a plain file or Directory
- //
- // Before using this function, initialize sSavedString to the text for
- // the Button title, using the carat (^) character as a place holder
- // for the directory name. Normally, you'll make this the Button title
- // in your custom dialog box.
- //
- // On entry, ioSelectName is the name of the file or directory
- // On exit, ioSelectName may be truncated to fit in the Button
- //
- // Sets sCurrentName to entry value of ioSelectName
-
- void
- UStandardFiles::SetSelectButtonTitle(
- ControlHandle inButtonH,
- const Rect & inButtonRect,
- Str63 ioSelectName )
- {
- // Save directory name
- ::BlockMoveData( ioSelectName, sCurrentName, StrLength(ioSelectName)+1 );
-
- // Truncate name if necessary to fit inside the Button
- short maxNameWidth = ( inButtonRect.right - inButtonRect.left) -
- ::StringWidth(sSavedString) - ::CharWidth(' ');
- ::TruncString( maxNameWidth, ioSelectName, smTruncMiddle );
-
- // Insert (truncated) selected item name into original button title
- Str255 buttonName;
- short len = StrLength( sSavedString );
- // Copy original name up to (but not including) the special marker
- short i = 1;
- while ( (i <= len) && (sSavedString[i] != replaceBy_thisName) ) {
- buttonName[i] = sSavedString[i];
- i++;
- }
-
- // Append directory name
- ::BlockMoveData( ioSelectName+1, buttonName+i, StrLength(ioSelectName) );
- // Append remaining part of original name (excluding the marker)
- short j = i + StrLength(ioSelectName) - 1;
- while ( ++i <= len ) {
- buttonName[++j] = sSavedString[i];
- }
- buttonName[0] = j;
-
- // Finally, we've got the Button name
- ::SetControlTitle( inButtonH, buttonName );
- ::ValidRect( &inButtonRect );
- }
-
-
- // ==================================================
- // Common functions
- // ==================================================
-
- // end of program
-